package com.ruoyi.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alipay.api.domain.AlipayFundTransToaccountTransferModel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ijpay.alipay.AliPayApi;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.kit.IpKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfig;
import com.ijpay.wxpay.WxPayApiConfigKit;
import com.ijpay.wxpay.model.TransferModel;
import com.ruoyi.business.app.bo.AppWithdrawApplyQueryBo;
import com.ruoyi.business.app.vo.WalletWithdrawRecordVo;
import com.ruoyi.business.bo.HcxWithdrawApplyAddBo;
import com.ruoyi.business.bo.HcxWithdrawApplyEditBo;
import com.ruoyi.business.bo.HcxWithdrawApplyQueryBo;
import com.ruoyi.business.domain.HcxAppUser;
import com.ruoyi.business.domain.HcxWithdrawApply;
import com.ruoyi.business.domain.HcxWithdrawDetail;
import com.ruoyi.business.enums.WithdrawEnum;
import com.ruoyi.business.mapper.HcxWithdrawApplyMapper;
import com.ruoyi.business.service.IHcxAppUserService;
import com.ruoyi.business.service.IHcxWithdrawApplyService;
import com.ruoyi.business.service.IHcxWithdrawDetailService;
import com.ruoyi.business.vo.HcxWithdrawApplyVo;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.AssertUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 提现申请Service业务层处理
 *
 * @author wsdz
 * @date 2022-08-26
 */
@Service
@AllArgsConstructor
@Slf4j
public class HcxWithdrawApplyServiceImpl extends ServicePlusImpl<HcxWithdrawApplyMapper, HcxWithdrawApply> implements IHcxWithdrawApplyService {

    private final IHcxAppUserService hcxAppUserService;

    private final IHcxWithdrawDetailService iHcxWithdrawDetailService;

    private final HcxWithdrawApplyMapper hcxWithdrawApplyMapper;

    @Override
    public HcxWithdrawApplyVo queryById(Long id) {
        return getVoById(id, HcxWithdrawApplyVo.class);
    }

    @Override
    public TableDataInfo<HcxWithdrawApplyVo> queryPageList(HcxWithdrawApplyQueryBo bo) {
        PagePlus<HcxWithdrawApply, HcxWithdrawApplyVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), HcxWithdrawApplyVo.class);
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public TableDataInfo<WalletWithdrawRecordVo> queryAppPageList(AppWithdrawApplyQueryBo bo) {
        PagePlus<HcxWithdrawApply, WalletWithdrawRecordVo> result = pageVo(PageUtils.buildPagePlus(), buildAppQueryWrapper(bo), WalletWithdrawRecordVo.class);
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<HcxWithdrawApplyVo> queryList(HcxWithdrawApplyQueryBo bo) {
        return listVo(buildQueryWrapper(bo), HcxWithdrawApplyVo.class);
    }

    private LambdaQueryWrapper<HcxWithdrawApply> buildQueryWrapper(HcxWithdrawApplyQueryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<HcxWithdrawApply> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, HcxWithdrawApply::getUserId, bo.getUserId());
        lqw.eq(bo.getAmount() != null, HcxWithdrawApply::getAmount, bo.getAmount());
        lqw.like(StrUtil.isNotBlank(bo.getUserName()), HcxWithdrawApply::getUserName, bo.getUserName());
        lqw.like(StrUtil.isNotBlank(bo.getNickName()), HcxWithdrawApply::getNickName, bo.getNickName());
        lqw.eq(bo.getServiceFeeProportion() != null, HcxWithdrawApply::getServiceFeeProportion, bo.getServiceFeeProportion());
        lqw.eq(StrUtil.isNotBlank(bo.getPhonenumber()), HcxWithdrawApply::getPhonenumber, bo.getPhonenumber());
        lqw.eq(bo.getBankCardId() != null, HcxWithdrawApply::getBankCardId, bo.getBankCardId());
        lqw.like(StrUtil.isNotBlank(bo.getRealName()), HcxWithdrawApply::getRealName, bo.getRealName());
        lqw.eq(bo.getApplyStatus() != null, HcxWithdrawApply::getApplyStatus, bo.getApplyStatus());
        lqw.eq(StrUtil.isNotBlank(bo.getDelFlag()), HcxWithdrawApply::getDelFlag, bo.getDelFlag());
        lqw.like(StrUtil.isNotBlank(bo.getBankName()), HcxWithdrawApply::getBankName, bo.getBankName());
        lqw.like(StrUtil.isNotBlank(bo.getTxType()), HcxWithdrawApply::getTxType, bo.getTxType());
        lqw.like(StrUtil.isNotBlank(bo.getBankCardNo()), HcxWithdrawApply::getBankCardNo, bo.getBankCardNo());
        lqw.like(StrUtil.isNotBlank(bo.getBankCardUserName()), HcxWithdrawApply::getBankCardUserName, bo.getBankCardUserName());
        lqw.like(StrUtil.isNotBlank(bo.getBankCardUserPhone()), HcxWithdrawApply::getBankCardUserPhone, bo.getBankCardUserPhone());
        lqw.eq(bo.getServiceCharge() != null, HcxWithdrawApply::getServiceCharge, bo.getServiceCharge());
        lqw.orderByDesc(HcxWithdrawApply::getCreateTime);
        return lqw;
    }

    private LambdaQueryWrapper<HcxWithdrawApply> buildAppQueryWrapper(AppWithdrawApplyQueryBo bo) {
        LambdaQueryWrapper<HcxWithdrawApply> lqw = Wrappers.lambdaQuery();
        lqw.eq(HcxWithdrawApply::getUserId, SecurityUtils.getUserId());
        lqw.orderByDesc(HcxWithdrawApply::getCreateTime);
        return lqw;
    }

    @Override
    public Boolean insertByAddBo(HcxWithdrawApplyAddBo bo) {
        HcxWithdrawApply add = BeanUtil.toBean(bo, HcxWithdrawApply.class);
        validEntityBeforeSave(add);
        return save(add);
    }

    @Override
    public Boolean updateByEditBo(HcxWithdrawApplyEditBo bo) {
        HcxWithdrawApply update = BeanUtil.toBean(bo, HcxWithdrawApply.class);
        validEntityBeforeSave(update);
        return updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(HcxWithdrawApply entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }

    @Override
    public String importHcxWithdrawApply(List<HcxWithdrawApplyVo> hcxWithdrawApplyList) {
        AssertUtils.isTrue(CollectionUtils.isNotEmpty(hcxWithdrawApplyList), "导入数据不能为空");
        int successNum = 0;
        for (HcxWithdrawApplyVo hcxWithdrawApply : hcxWithdrawApplyList) {
            HcxWithdrawApply add = BeanUtil.toBean(hcxWithdrawApply, HcxWithdrawApply.class);
            save(add);
            successNum++;
        }
        String msg = String.format("导入完成，共计 %d 条数据，成功 %d 条！", hcxWithdrawApplyList.size(), successNum);
        if (successNum != hcxWithdrawApplyList.size()) {
            msg = msg + String.format("失败 %d 条！", hcxWithdrawApplyList.size() - successNum);
        }
        return msg;
    }

    @Override
    @Transactional
    public Boolean audit(HcxWithdrawApplyEditBo bo) throws Exception {

        Boolean result = true;
        // 修改申请信息
        HcxWithdrawApply hcxWithdrawApply = hcxWithdrawApplyMapper.selectById(bo.getId());

        // 用户
        HcxAppUser hcxAppUser = hcxAppUserService.getById(bo.getUserId());

        // 如果审核通过 扣减余额
        if (Constants.ONE.equals(bo.getApplyStatus())) {


            // 审核通过后 打款到支付宝账号
            if (hcxWithdrawApply.getBankName().equals("支付宝")) {

                AlipayFundTransToaccountTransferModel model = new AlipayFundTransToaccountTransferModel();
                // 编号
                String format = DateUtil.format(new Date(), "yyyyMMddHHmmss");
                String numbers = RandomUtil.randomNumbers(5);
                String orderNum = "AL" + format + numbers;

                log.info("支付宝outBizNo------------>{}", orderNum);

                model.setOutBizNo(orderNum);
                model.setPayeeType("ALIPAY_LOGONID");
                model.setPayeeAccount(hcxWithdrawApply.getBankCardNo());
                model.setAmount(hcxWithdrawApply.getAmount().subtract(hcxWithdrawApply.getServiceCharge()).toString());
                model.setPayerShowName("宿迁市友家农业旅游有限公司");
                model.setPayeeRealName(hcxWithdrawApply.getRealName());
                model.setRemark("提现到" + hcxWithdrawApply.getBankCardNo());

                String body = AliPayApi.transferToResponse(model).getBody();
                log.info("支付宝返回的消息------------>{}", body);

                JSONObject jsonObject = JSONUtil.parseObj(body);
                String alipayFundTrans = jsonObject.getStr("alipay_fund_trans_toaccount_transfer_response");
                JSONObject jsonObject1 = JSONUtil.parseObj(alipayFundTrans);


                AssertUtils.isTrue(ObjectUtil.isNotEmpty(jsonObject1.getStr("msg")) && jsonObject1.getStr("msg").equals("Success"), "支付宝提现失败!");


                // 转账成功
                hcxWithdrawApply.setApplyStatus(bo.getApplyStatus());
                hcxWithdrawApply.setOperOpition(bo.getOperOpition());
                result = updateById(hcxWithdrawApply);




                // 审核通过后生成提现账单明细
                HcxWithdrawDetail hcxWithdrawDetail = new HcxWithdrawDetail();
                hcxWithdrawDetail.setUserId(bo.getUserId());
                if (Constants.ZERO.equals(bo.getTxType())) {
                    hcxWithdrawDetail.setDetailType(Constants.ZERO);
                } else {
                    hcxWithdrawDetail.setDetailType(Constants.ONE);
                }
                hcxWithdrawDetail.setAmount(hcxWithdrawApply.getAmount());
                hcxWithdrawDetail.setPhonenumber(hcxAppUser.getPhonenumber());
                hcxWithdrawDetail.setRealName(hcxAppUser.getRealName());
                result = iHcxWithdrawDetailService.save(hcxWithdrawDetail);


            }
            // 审核通过后 打款到微信
            if (hcxWithdrawApply.getBankName().equals("微信")) {
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                weixinTixian(request, hcxWithdrawApply.getBankCardNo(), hcxWithdrawApply.getAmount().subtract(hcxWithdrawApply.getServiceCharge()));
            }
        } else if(Constants.THREE.equals(bo.getApplyStatus())){

            // 审核不通过 再把用户钱包的钱加回去

            if (WithdrawEnum.YETX.getValue().equals(bo.getTxType())) {
                // 如果是余额提现申请   扣减金额=提现金额+手续费金额
                hcxAppUser.setBalancePrice(hcxAppUser.getBalancePrice().add(hcxWithdrawApply.getAmount()).add(hcxWithdrawApply.getServiceCharge()).setScale(2, BigDecimal.ROUND_HALF_UP));
            } else if (WithdrawEnum.TGJTX.getValue().equals(bo.getTxType())) {
                // 如果是推广奖提现申请  扣减金额=提现金额+手续费金额
                hcxAppUser.setSharePrice(hcxAppUser.getSharePrice().add(hcxWithdrawApply.getAmount()).add(hcxWithdrawApply.getServiceCharge()).setScale(2, BigDecimal.ROUND_HALF_UP));
            } else if (WithdrawEnum.MDSRTX.getValue().equals(bo.getTxType())) {
                // 如果是门店收入提现申请  扣减金额=提现金额+手续费金额
                hcxAppUser.setMerchantPrice(hcxAppUser.getMerchantPrice().add(hcxWithdrawApply.getAmount()).add(hcxWithdrawApply.getServiceCharge()).setScale(2, BigDecimal.ROUND_HALF_UP));
            }
            hcxAppUserService.updateById(hcxAppUser);



        }
        return result;
    }

    @Override
    public Boolean daozhang(List<Long> ids) {
        List<HcxWithdrawApply> list = list(new LambdaQueryWrapper<HcxWithdrawApply>().in(HcxWithdrawApply::getId, ids));
        for (HcxWithdrawApply hcxWithdrawApply : list) {
            hcxWithdrawApply.setApplyStatus(Constants.TWO);
        }
        return updateBatchById(list);
    }

    /**
     * @description:企业付款到零钱
     * @author: kubilewang
     * @date: 2023/2/3 11:36
     * @param:
     * @param: request
     * @param: openId
     * @Return: void
     **/
    public void weixinTixian(HttpServletRequest request, String openId, BigDecimal tixianPrice) {

        // 应付金额转换为分
        int fen = tixianPrice.movePointRight(2).intValue();

        HcxAppUser hcxAppUser = hcxAppUserService.getOne(new LambdaQueryWrapper<HcxAppUser>().eq(HcxAppUser::getOpenId, openId));

        String ip = IpKit.getRealIp(request);
        if (StrUtil.isBlank(ip)) {
            ip = "127.0.0.1";
        }

        WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig();
        Map<String, String> params = TransferModel.builder()
                .mch_appid(wxPayApiConfig.getAppId())
                .mchid(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .partner_trade_no(WxPayKit.generateStr())
                .openid(openId)
                .check_name("NO_CHECK")
                .amount(String.valueOf(fen))
                .desc("微信转账给" + hcxAppUser.getNickName())
                .spbill_create_ip(ip)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5, false);

        // 提现
        String transfers = WxPayApi.transfers(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
        log.info("提现结果:" + transfers);
    }
}
